﻿using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using IdeaBlade.EntityModel;
using IdeaBlade.Validation;

using CoProjectDF.Web.Resources;

namespace CoProjectDF.Models.Login
{

    /// <summary>
    /// Extensions to RegistrationData.  
    /// </summary>
    public partial class RegistrationData : VerifiableObject
    {

        [Display(Order = 3, Name = "PasswordLabel", Description = "PasswordDescription", ResourceType = typeof(RegistrationDataResources))]
        [Required(ErrorMessageResourceName = "ValidationErrorRequiredField", ErrorMessageResourceType = typeof(ValidationErrorResources))]
        [RegexVerifier("Password", "^.*[^a-zA-Z0-9].*$", ErrorMessageResourceName = "ValidationErrorBadPasswordStrength")]
        [StringLengthVerifier(MaxValue = 50, MinValue = 7, ErrorMessageResourceName = "ValidationErrorBadPasswordLength")]
        public string Password
        {
            get { return (this.PasswordAccessor == null) ? string.Empty : this.PasswordAccessor(); }
            set { base.SetProperty<string>("Password", value, null); }
        }

        [Display(Order = 4, Name = "PasswordConfirmationLabel", ResourceType = typeof(RegistrationDataResources))]
        [Required(ErrorMessageResourceName = "ValidationErrorRequiredField", ErrorMessageResourceType = typeof(ValidationErrorResources))]
        public string PasswordConfirmation
        {
            get { return (this.PasswordConfirmationAccessor == null) ? string.Empty : this.PasswordConfirmationAccessor(); }
            set { base.SetProperty<string>("PasswordConfirmation", value, null); }
        }

        internal Func<string> PasswordAccessor { get; set; }
        internal Func<string> PasswordConfirmationAccessor { get; set; }

        public ILoginCredential ToLoginCredential()
        {
            return new FormsAuthenticationLoginCredential(UserName, Password, string.Empty, false);
        }

        #region Custom client-side verifiers

        public class RegistrationVerifierProvider : IVerifierProvider
        {

            public IEnumerable<Verifier> GetVerifiers(object verifierProviderContext)
            {
                yield return RegistrationData.PasswordConfirmationVerifier();
            }
        }

        private static Verifier PasswordConfirmationVerifier()
        {

            // Define the verification test. 
            VerifierCondition<RegistrationData> condition = (reg, trigger, ctx) =>
            {
                if (string.IsNullOrWhiteSpace(reg.Password) || string.IsNullOrWhiteSpace(reg.PasswordConfirmation))
                {
                    return new VerifierResult(VerifierResultCode.OkNotApplicable);
                }
                return new VerifierResult(reg.Password == reg.PasswordConfirmation);
            };

            // Create the verifier.
            var args = new DelegateVerifierArgs<RegistrationData>("Password mismatch", null, condition);
            args.ErrorMessageInfo.ResourceName = "ValidationErrorPasswordConfirmationMismatch";
            var verifier = new DelegateVerifier<RegistrationData>(args);

            // Runs after setter called, and when entire entity is verified.
            verifier.VerifierOptions.ExecutionModes = VerifierExecutionModes.InstanceAndOnAfterSetTriggers;

            // Triggered by changes to Password or PasswordConfirmation
            verifier.AddTriggers("Password", "PasswordConfirmation");
            return verifier;
        }
        #endregion
    }
}
